home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
LDB171.ARJ
/
MUTUAL.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-12
|
12KB
|
565 lines
/*
mutual.cpp -- Loose Data Binder v 1.7:
mutually owned and persistence
(C) Copyright 1992 John W. Small
All rights reserved
PSW / Power SoftWare
P.O. Box 10072
McLean, Virginia 22102 8072 USA
(703) 759-3838
*/
#ifndef Mutual_HPP
#include "mutual.hpp"
#endif
/** Mutual Class **/
Mutual::Mutual(initMutual)
{
parenT = voiD0;
refCount = streamCount = 0U;
streamPos = 0L;
}
void Mutual::serror(const char *msg, unsigned id)
{
if (streamDebug)
cerr << endl
<< "Class id: " << setw(6) << id
<< " stream error - "
<< msg << endl;
}
void Mutual::error(const char *msg)
{
if (streamDebug)
cerr << endl
<<"Class id: " << setw(6) << ID()
<< " &instance: "
<< (void *) this << endl
<< "Stream error - "
<< msg << endl;
}
void Mutual::warn(const char *msg)
{
if (streamDebug)
cerr << endl
<< "Class id: " << setw(6) << ID()
<< " &instance: "
<< (void *) this << endl
<< "Stream warning - "
<< msg << endl;
}
int Mutual::refDebug = 0;
int Mutual::streamDebug = 0;
char Mutual::memberTermChar = '\n';
void Mutual::RegisterClass(unsigned id,
MutuaL (*fgeT)(istream&, MutuaL))
{
StreamReg.RegisterClass(id,fgeT);
}
unsigned Mutual::restream()
{
unsigned underFlow = (streamPos?
refCount - streamCount : 0);
streamCount = 0;
streamPos = 0L;
if (underFlow)
warn("restream: streamed less than "
"referenced");
return underFlow;
}
void Mutual::unlink(voiD P)
{
if (refDebug)
if (refCount)
cerr << endl
<< "Class id: " << setw(6) << ID()
<< " &instance: "
<< (void *) this << endl
<< "Unlinking, starting refCount: "
<< refCount << endl;
else
cerr << endl
<< "Class id: " << setw(6) << ID()
<< " &instance: "
<< (void *) this << endl
<< "unlink() underflow" << endl;
if (refCount)
--refCount;
if (parenT == P || !refCount)
parenT = voiD0;
}
int Mutual::link(voiD P)
{
if (refCount >= UINT_MAX) {
if (refDebug)
cerr << endl
<< "Class id: " << setw(6) << ID()
<< " &instance: "
<< (void *) this << endl
<< "link() overflow" << endl;
return 0;
}
refCount++;
if (!parenT && P)
parenT = P;
if (refDebug)
cerr << endl
<< "Class id: " << setw(6) << ID()
<< " &instance: "
<< (void *) this << endl
<< "Adding link, new refCount: "
<< refCount << endl;
return 1;
}
/** MBinder Class **/
voiD MBinder::Dassign(voiD D, const voiD S)
{
// invokes Mutual's overloaded operator=()
if ((*(MutuaL)D) = (*(MutuaL)S))
return D;
return voiD0;
}
voiD MBinder::Dnew(const voiD D)
{
// invokes Mutual's copy initializer constructor
return (voiD) ((MutuaL)D)->clone();
}
void MBinder::Ddelete(voiD D)
{
// invokes Mutual's destructor
if (!((MutuaL)D)->RefCount())
delete (MutuaL) D;
}
void MBinder::Dstore(ostream& os, voiD D)
{
// invokes operator<<(ostream&,Mutual&)
os << *(MutuaL)D;
}
voiD MBinder::Dload(istream& is)
{
MutuaL M;
// invokes operator>>(istream&,MutuaL&)
is >> M;
return (voiD) M;
}
MBindeR MBinder::load(istream& is, MBindeR thiS)
{
int newed;
if (thiS)
newed = 0;
else {
if ((thiS = new MBinder(initVFTsOnly))
== MBindeR0) {
sberror("unable to construct "
"new MBinder for "
"loading");
return MBindeR0;
}
newed = 1;
}
if (!Binder::load(is,(BindeR)thiS)) {
if (newed)
delete (voiD) thiS;
return MBindeR0;
}
return thiS;
}
unsigned MBinder::restream()
{
MutuaL M;
unsigned result = Mutual::restream();
for (unsigned i = 0;
(M = (MutuaL) atGet(i)) != MutuaL0;
i++)
M->restream();
return result;
}
/** StreamRegistry Class, etc. **/
struct StreamClassRecord {
unsigned id;
MutuaL (*fgeT)(istream&, MutuaL);
StreamClassRecord(unsigned id,
MutuaL (*fgeT)(istream&, MutuaL))
{ this->id = id; this->fgeT = fgeT; }
~StreamClassRecord() {}
};
typedef struct StreamClassRecord * SCRecorD;
#define SCRecorD0 ((SCRecorD)0)
struct StreamInstanceRecord {
MutuaL InstancE;
unsigned refCount, streamCount;
long streamPos;
StreamInstanceRecord(MutuaL InstancE,
unsigned refCount, long streamPos)
{
this->InstancE = InstancE;
this->refCount = refCount;
streamCount = 1;
this->streamPos = streamPos;
}
~StreamInstanceRecord() {}
};
typedef struct StreamInstanceRecord * SIRecorD;
#define SIRecorD0 ((SIRecorD)0)
struct StreamFunctionRecord {
unsigned id;
GenericFnC fnC;
StreamFunctionRecord(unsigned id,
GenericFnC fnC)
{ this->id = id; this->fnC = fnC; }
~StreamFunctionRecord() {}
};
typedef struct StreamFunctionRecord * SFRecorD;
#define SFRecorD0 ((SFRecorD)0)
void StreamRegistry::CIerror(char *msg, unsigned id,
MutuaL InstancE)
{
if (debug)
cerr << endl
<< "Class id: " << setw(6) << id
<< " &instance: "
<< (void *) InstancE << endl
<< "Class Registry error - "
<< msg << endl;
}
void StreamRegistry::CIwarn(char *msg, unsigned id,
MutuaL InstancE)
{
if (debug)
cerr << endl
<< "Class id: " << setw(6) << id
<< " &instance: "
<< (void *) InstancE << endl
<< "Class Registry warning - "
<< msg << endl;
}
void StreamRegistry::FNCerror(char *msg, unsigned id)
{
if (debug)
cerr << endl
<< "Function id: " << setw(6)
<< id << endl
<< "Function Registry error - "
<< msg << endl;
}
void StreamRegistry::FNCwarn(char *msg, unsigned id)
{
if (debug)
cerr << endl
<< "Function id: " << setw(6)
<< id << endl
<< "Function Registry warning - "
<< msg << endl;
}
int StreamRegistry::debug = 0;
unsigned StreamRegistry::restream()
{
unsigned underFlow = InstanceRecords.Nodes();
SIRecorD R;
for (unsigned i = 0; i < underFlow; i++) {
R = (SIRecorD) InstanceRecords.atGet(i);
CIwarn("Restream: holding pen under-linked",
R->InstancE->ID(),R->InstancE);
}
InstanceRecords.allDel();
return underFlow;
}
void StreamRegistry::RegisterClass(unsigned id,
MutuaL (*fgeT) (istream&, MutuaL))
{
unsigned i;
for (i = 0; i < ClassRecords.Nodes(); i++)
if (((SCRecorD)ClassRecords[i])->id
== id)
break;
if (i < ClassRecords.Nodes())
if (((SCRecorD)ClassRecords[i])->fgeT
== fgeT) {
CIwarn("multiple registration of"
" loader",id);
return;
}
else {
CIerror("id conflict",id);
return;
}
SCRecorD R = new StreamClassRecord(id,fgeT);
if (!R)
CIerror("class record memory exhausted",
id);
else if (!ClassRecords.insQ((voiD)R)) {
CIerror("class record can't be queued",
id);
delete R;
}
}
void StreamRegistry::registerFunction(unsigned id,
GenericFnC fnC)
{
unsigned i;
for (i = 0; i < FunctionRecords.Nodes(); i++)
if (((SFRecorD)FunctionRecords[i])->id
== id) break;
if (i < FunctionRecords.Nodes())
if (((SFRecorD)FunctionRecords[i])->fnC
== fnC)
{
FNCwarn("attempted multiple"
" registration"
" of function",
id);
return;
}
else {
FNCerror("id conflict",id);
return;
}
SFRecorD R = new StreamFunctionRecord(id,fnC);
if (!R)
FNCerror("fnC memory exhausted",id);
else if (!FunctionRecords.insQ((voiD)R)) {
FNCerror("fnC record can't be queued",
id);
delete R;
}
}
GenericFnC StreamRegistry::fnCLU(unsigned id)
{
unsigned i;
for (i = 0; i < FunctionRecords.Nodes(); i++)
if (((SFRecorD)FunctionRecords[i])->id
== id) break;
if (i >= FunctionRecords.Nodes()) {
FNCerror("unknown function",id);
return GenericFnC0;
}
else
return ((SFRecorD)FunctionRecords[i])->fnC;
}
unsigned StreamRegistry::fnCID(GenericFnC fnC)
{
unsigned i;
for (i = 0; i < FunctionRecords.Nodes(); i++)
if (((SFRecorD)FunctionRecords[i])->fnC
== fnC)
break;
if (i >= FunctionRecords.Nodes()) {
FNCerror("unknown function",
ID_UnknownGenericFnC);
return ID_UnknownGenericFnC;
}
else
return ((SFRecorD)FunctionRecords[i])->id;
}
void StreamRegistry::forgetRegistrations()
{
ClassRecords.allDel();
InstanceRecords.allDel();
FunctionRecords.allDel();
}
void StreamRegistry::fput(ostream& os, Mutual& Instance)
{
unsigned id, i;
long streamPos;
id = Instance.ID();
for (i = 0; i < ClassRecords.Nodes(); i++)
if (((SCRecorD)ClassRecords[i])->id == id)
break;
if (i >= ClassRecords.Nodes()) {
CIerror("attempted store of unknown class",
id);
}
else if (Instance.refCount <= Instance.streamCount)
CIerror("more stores attempted than links",
id,&Instance);
else {
Instance.streamCount++;
if (Instance.streamPos) {
// already stored!
if (!(os << ID_MRef << Mendm
<< Instance.streamPos
<< Mendm))
CIerror("unable to store "
"multiple reference",
id,&Instance);
}
else { // Never store object at streamPos 0
if ((streamPos = os.tellp()) == 0)
if (!(os << ID_MRef << Mendm))
CIerror("unable to skip "
"streamPos 0");
else
streamPos = os.tellp();
if (!(os << id << Mendm))
CIerror("unable to store id",
id,&Instance);
else {
Instance.streamPos = streamPos;
if (!(os << Instance.refCount
<< Mendm))
CIerror("unable to store "
"refCount ",id,
&Instance);
else
Instance.fput(os);
}
}
}
os << flush;
}
void StreamRegistry::fget(istream& is, MutuaL& InstancE)
{
unsigned id, refCount, i;
long streamPos;
SIRecorD R;
InstancE = MutuaL0;
if ((streamPos = is.tellg()) == 0)
if (!(is >> id >> Mnextm)) {
CIerror("unable to strip skip 0");
return;
}
else
streamPos = is.tellg();
if (!(is >> id >> Mnextm)) {
CIerror("unable to read id");
return;
}
if (id == ID_MRef) {
// link to previously loaded Instance
if (!(is >> streamPos >> Mnextm)) {
CIerror("unable to read streamPos");
return;
}
for (i = 0; i < InstanceRecords.Nodes(); i++)
if ((R = (SIRecorD)InstanceRecords[i])
->streamPos == streamPos) {
// found saved instance!
InstancE = R->InstancE;
if (R->refCount <= ++R->streamCount)
// discard when done!
InstanceRecords.atRmv(i);
break;
}
if (!InstancE)
CIerror("unable to establish link to"
" previously loaded class",
id);
}
else { // load instance
if (!(is >> refCount >> Mnextm)) {
CIerror("unable to read refCount",id);
return;
}
for (i = 0; i < ClassRecords.Nodes(); i++)
if (((SCRecorD)ClassRecords[i])->id
== id)
break;
if (i >= ClassRecords.Nodes()) {
CIerror("attempted load of unknown "
"class",id);
return;
}
if ((InstancE = (*((SCRecorD)
ClassRecords[i])->fgeT)
(is,MutuaL0)) == MutuaL0)
{
CIerror("unable to load instance",id);
return;
}
if (refCount > 1) {
// 1st of many - save in holding pen
R = new StreamInstanceRecord
(InstancE,refCount,streamPos);
if (!R)
CIerror("instance holding record"
" memory exhausted",
id,InstancE);
else if (!InstanceRecords.insQ
((voiD)R)) {
CIerror("unable to hold "
"instance for "
"multiple links",
id,InstancE);
delete R;
}
}
}
}
StreamRegistry StreamReg;
ostream& Mendm(ostream& os)
{
return os << Mutual::memberTermChar << flush;
}
istream& Mnextm(istream& is)
{
is.get();
return is;
}